package cate.game.role.bag.inscription;

import cate.common.table.d.GDInscription;
import cate.common.table.item.inscription.row.InscriptionBaseRow;
import cate.common.table.item.inscription.row.InscriptionGridOpenRow;
import cate.common.util.GameResult;
import cate.game.attr.FightAttr;
import cate.game.event.hero.HeroPowerChangeEvent;
import cate.game.play.support.PlayBuildContext;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.bag.BagContainer;
import cate.game.role.bag.hero.Hero;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@NoteClass("铭文页")
public class InscriptionPage extends RoleDependent {

    public int id;

    @NoteField("装备了此铭文页的英雄")
    public List<String> owners;

    @NoteField("铭文格子")
    public Map<Byte, String> uidMap;

    @NoteField("铭文页名字")
    public String name;

    @NoteField("需要解锁且已解锁的铭文格子")
    public List<Byte> openedPos;

    public InscriptionPage() {
    }

    public InscriptionPage(Role role) {
        super(role);
        initialize(role);
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (owners == null) {
            owners = new ArrayList<>();
        }
        if (uidMap == null) {
            uidMap = new HashMap<>();
        }
        if (openedPos == null) {
            openedPos = new ArrayList<>();
        }
    }

    //装备铭文到铭文页
    public GameResult<Byte> put(byte pos, Inscription inscription) {
        GameResult<Byte> result = new GameResult<>();
        InscriptionGridOpenRow row = getRow(pos);
        if (row == null) {
            return result.fail("读不到格子配置");
        }
        if (uidMap.containsValue(inscription.uid)) {
            return result.fail("铭文已装配在本页其他格子");
        }
        if (row.needOpen == 1 && !openedPos.contains(pos)) {
            return result.fail("请先解锁此格子");
        }
        InscriptionBaseRow baseRow = inscription.getTpl(role.getGame());
        if (baseRow == null) {
            return result.fail("读不到配置2");
        }
        if (baseRow.pageType != row.pageType) {
            return result.fail("铭文不能装配在此区域");
        }
        long count = uidMap.keySet().stream().filter(posOn ->
                {
                    String item = uidMap.get(posOn);
                    Inscription i = findInscription(item);
                    if (i != null) {
                        InscriptionBaseRow tpl = findInscription(item).getTpl(role.getGame());
                        return tpl.pageType == baseRow.pageType && tpl.detailType == baseRow.detailType && posOn != pos;
                    }
                    return false;
                }
        ).count();
        if (count >= baseRow.limitNum) {
            return result.fail("同类型铭文穿戴已达上限");
        }
        uidMap.put(pos, inscription.uid);
        result.data = pos;
        updatePower();
        return result.success();
    }

    @JsonIgnore
    public Hero getHero(Role role, String heroUid) {
        return role.getBag().hero.getItem(heroUid);
    }

    @JsonIgnore
    public BagContainer<Inscription> getItemBag() {
        return role.getBag().inscription;
    }

    @JsonIgnore
    public InscriptionGridOpenRow getRow(int pos) {
        return role.getGame().table.inscription.gridOpen.get(pos);
    }

    public GameResult<Byte> off(byte pos) {
        GameResult<Byte> r = new GameResult<>();
        if (uidMap.get(pos) == null) {
            return r.fail("格子为空");
        }
        uidMap.remove(pos);
        updatePower();
        r.data = pos;
        return r;
    }

    @JsonIgnore
    public FightAttr getPowerAttr(PlayBuildContext ctx) {
        FightAttr attr = new FightAttr();
        for (String i :
                uidMap.values()) {
            Inscription inscription = findInscription(i);
            if (inscription == null || inscription.getTpl(ctx).pageType == GDInscription.SKILL_INSCRIPTION) {
                continue;
            }
            attr.add(inscription.getPowerAttr(ctx));
        }
        return attr;
    }


    public List<Integer> getSkills(PlayBuildContext ctx) {
        List<Integer> skills = new ArrayList<>();
        //计算出除技能铭文外的铭文总等级
        int totalLevel = uidMap.values().stream()
                .filter(id -> findInscription(id).getTpl(ctx).pageType != GDInscription.SKILL_INSCRIPTION)
                .mapToInt(uid -> {
                    Inscription i = findInscription(uid);
                    if (i != null) {
                        return i.getTpl(ctx).level;
                    }
                    return 0;

                }).sum();
        //取出技能铭文
        List<Byte> inscriptions = uidMap.keySet().stream()
                .filter(pos -> {
                    Inscription ins = findInscription(uidMap.get(pos));
                    return ins.getTpl(ctx).pageType == GDInscription.SKILL_INSCRIPTION;})
                .collect(Collectors.toList());
        if (inscriptions.isEmpty()) {
            return skills;
        }
        for (Byte inscriptionPos : inscriptions) {
            InscriptionGridOpenRow openRow = role.getGame().table.inscription.gridOpen.get((int)inscriptionPos);
            if (openRow == null || totalLevel < openRow.skillActiveLevel) {
                continue;
            }
            Inscription inscription = findInscription(uidMap.get(inscriptionPos));
            int skillId = inscription.getSkill(ctx);
            if (skillId > 0) {
                skills.add(skillId);
            }
        }
        return skills;
    }

    private void updatePower() {
        boolean flag = false;
        for (String heroUid : new ArrayList<>(owners)) {
            Hero hero = getHero(role, heroUid);
            if (hero != null) {
                flag = true;
                role.getGame().eventDispatcher.dispatchEvent(new HeroPowerChangeEvent(hero.getRole(), hero));
            }else {
                owners.remove(heroUid);
            }
        }
        if (flag) {
            role.getBase().updatePower();
        }
    }

    public GameResult<InscriptionPage> openGrid(byte pos) {
        GameResult<InscriptionPage> r = new GameResult<>();
        InscriptionGridOpenRow openRow = role.getGame().table.inscription.gridOpen.get((int) pos);
        if (openRow == null) {
            return r.fail("格子不存在");
        }
        if (openRow.needOpen != 1 || openedPos.contains(pos)) {
            return r.fail("此格子已开启");
        }
        if (StringUtils.isBlank(openRow.openCost)) {
            return r.fail("消耗未配置");
        }
        MixRes consume = new MixRes(openRow.openCost);
        GameResult<MixResItem> cResult = consume.consume(role);
        if (!cResult.ok()) {
            return r.fail(cResult);
        }
        openedPos.add(pos);
        r.data = this;
        return r;
    }

    @JsonIgnore
    private Inscription findInscription(String uid) {
        return role.getBag().inscription.getItem(uid);
    }

    @Override
    public void onEnter() {
        super.onEnter();
    }

}
